package org.itzheng.myrxframe.realize.adpter.rcv;

import android.annotation.TargetApi;
import android.app.usage.StorageStats;
import android.app.usage.StorageStatsManager;
import android.content.Context;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageStats;
import android.os.Build;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.support.v7.widget.RecyclerView;
import android.text.format.Formatter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;

import org.itzheng.and.baseutils.common.ArrayUtils;
import org.itzheng.and.baseutils.common.StrUtils;
import org.itzheng.and.baseutils.ui.UIUtils;
import org.itzheng.and.recyclerview.adapter.BaseRecyclerAdapter;
import org.itzheng.myrxframe.R;
import org.itzheng.myrxframe.http.rxjava.RxHelper;
import org.itzheng.myrxframe.realize.apk.ApkListActivity;
import org.itzheng.myrxframe.realize.apk.utils.AppUtils;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.functions.Consumer;

/**
 * Title:<br>
 * Description: <br>
 *
 * @email ItZheng@ZoHo.com
 * Created by itzheng on 2019-4-15.
 */
public class ApkListAdapter extends BaseRecyclerAdapter<ApkListAdapter.ViewHolder> {
    List<PackageInfo> mItems;
    PackageManager mPackageManager;
    /**
     * 选中列表
     */
    Map<String, Boolean> checkedMap = new HashMap<>();

    public ApkListAdapter(List<PackageInfo> items, PackageManager packageManager) {
        mItems = items;
        mPackageManager = packageManager;
    }

    @Override
    public View onCreateView(ViewGroup parent, int viewType) {
        return UIUtils.inflateAdapterView(R.layout.adapter_item_apk_list, parent);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ViewHolder(onCreateView(parent, viewType));
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        PackageInfo item = mItems.get(position);
        if (currentModel == ApkListActivity.Model.NORMAL) {
            holder.cbChecked.setVisibility(View.GONE);
            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    if (item.packageName.equalsIgnoreCase(v.getContext().getPackageName())) {
                        showToast("当前应用无法删除");
                    } else {
                        AppUtils.deleteApp(v.getContext(), item.packageName);
                    }
                    return false;
                }
            });
        } else {
            holder.itemView.setOnLongClickListener(null);
            holder.cbChecked.setChecked(isTrue(checkedMap.get(item.packageName)));
            holder.cbChecked.setVisibility(View.VISIBLE);
            holder.cbChecked.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    checkedApp((CheckBox) v, item.packageName);
                }
            });
        }
        holder.ivIcon.setImageDrawable(AppUtils.getAppIcon(mPackageManager, item));
        holder.tvName.setText(AppUtils.getAppName(mPackageManager, item));
        updateSize(holder.tvSize, item);
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (currentModel == ApkListActivity.Model.BACKUP) {
                    holder.cbChecked.performClick();
                    return;
                }
                if (item.packageName.equalsIgnoreCase(v.getContext().getPackageName())) {
                    showToast("当前应用已打开");
                    return;
                }
                AppUtils.openApp(v.getContext(), item.packageName, new AppUtils.IOpenAppResult() {
                    @Override
                    public void OnSuccess() {

                    }

                    @Override
                    public void OnError(String error) {
                        showToast(error);
                    }
                });
            }
        });
    }

    private boolean isTrue(Boolean aBoolean) {
        return aBoolean != null && aBoolean;
    }

    /**
     * 选中或取消app
     *
     * @param v
     * @param packageName
     */
    private void checkedApp(CheckBox v, String packageName) {
        if (v.isChecked()) {
            //false
            checkedMap.put(packageName, true);
        } else {
            checkedMap.remove(packageName);
        }
        updateCheckedCount();
    }

    /**
     * 校验选中数量
     */
    public void checkCheckedMap() {
        Observable.create(new ObservableOnSubscribe<Boolean>() {
            @Override
            public void subscribe(ObservableEmitter<Boolean> e) throws Exception {
                Map<String, Boolean> tempMap = new HashMap<>();
                for (PackageInfo item : mItems) {
                    //将当前mItems的包集合存到map中
                    tempMap.put(item.packageName, true);
                }
                Set<Map.Entry<String, Boolean>> entries = checkedMap.entrySet();
                //是否需要修改
                boolean isNotify = false;
                for (Map.Entry<String, Boolean> item : entries) {
                    //如果获取不到，说明当前列表不存在，移除
                    String key = (item.getKey());
                    if (!isTrue(tempMap.get(key))) {
                        checkedMap.remove(key);
                        isNotify = true;
                    }
                }
                e.onNext(isNotify);
                e.onComplete();
            }
        }).compose(RxHelper.observableIO2Main()).subscribe(new Consumer<Boolean>() {
            @Override
            public void accept(Boolean aBoolean) throws Exception {
                if (aBoolean) {
                    notifyDataSetChanged();
                    updateCheckedCount();
                }
            }
        });

    }

    /**
     * 更新数量变化
     */
    private void updateCheckedCount() {
        if (mOnCheckedCountChangeListener != null) {
            mOnCheckedCountChangeListener.onChange(checkedMap.size());
        }
    }

    private OnCheckedCountChangeListener mOnCheckedCountChangeListener;

    /**
     * 设置选中数量变化
     *
     * @param listener
     */
    public void setOnCheckedCountChangeListener(OnCheckedCountChangeListener listener) {
        mOnCheckedCountChangeListener = listener;
    }

    public Map<String, Boolean> getCheckedMap() {
        return checkedMap;
    }

    /**
     * 选中数量变化时调用
     */
    public interface OnCheckedCountChangeListener {
        /**
         * 选中的数量
         *
         * @param size
         */
        void onChange(int size);
    }

    private void showToast(String msg) {
        UIUtils.showToast(msg);
    }

    /**
     * 使用Rxjava更新大小
     *
     * @param tvSize
     * @param packageInfo
     */
    private void updateSize(TextView tvSize, PackageInfo packageInfo) {
        tvSize.setTag(packageInfo.packageName);
        Observable.create(new ObservableOnSubscribe<AppInfo>() {
            @Override
            public void subscribe(ObservableEmitter<AppInfo> oe) throws Exception {
                Context context = tvSize.getContext();
                AppInfo appInfo = new AppInfo();
                appInfo.PackageName = packageInfo.packageName;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    try {
                        StorageStats stats = null;
                        stats = queryStatsForPackage(context, appInfo.PackageName);//statsManager.queryStatsForPackage(StorageManager.UUID_DEFAULT, appInfo.PackageName, handler);
                        if (stats != null) {
                            long codeBytes = stats.getAppBytes();
                            long dataBytes = stats.getDataBytes();
                            long cacheBytes = stats.getCacheBytes();
                            appInfo.size = Formatter.formatFileSize(context, codeBytes + dataBytes + cacheBytes);
                        }
                    } catch (SecurityException e) { //这里说明没有权限，没有权限只能查询自身应用大小
                        e.printStackTrace();
                        appInfo.size = "No permission";
                    }
                    oe.onNext(appInfo);
                    oe.onComplete();
                } else {
                    //低版本使用AIDL反射获取
                    Method method = PackageManager.class.getMethod("getPackageSizeInfo",
                            new Class[]{String.class, IPackageStatsObserver.class});
                    // 调用 getPackageSizeInfo 方法，需要两个参数：1、需要检测的应用包名；2、回调
                    method.invoke(context.getPackageManager(), new Object[]{
                            appInfo.PackageName,
                            new IPackageStatsObserver.Stub() {
                                @Override
                                public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) throws RemoteException {
                                    long codeBytes = pStats.codeSize;
                                    long dataBytes = pStats.dataSize;
                                    long cacheBytes = pStats.cacheSize;
                                    appInfo.size = Formatter.formatFileSize(context, codeBytes + dataBytes + cacheBytes);
                                    oe.onNext(appInfo);
                                    oe.onComplete();
                                }
                            }
                    });
                }
            }
        }).compose(RxHelper.observableIO2Main()).subscribe(new Consumer<AppInfo>() {
            @Override
            public void accept(AppInfo appInfo) throws Exception {
                Object tag = tvSize.getTag();
                if (tag != null && tag.equals(appInfo.PackageName)) {
                    tvSize.setText(appInfo.size);
                }
            }
        });
    }

    StorageStatsManager mStorageStatsManager;
    UserHandle mUserHandle;

    @TargetApi(Build.VERSION_CODES.O)
    private StorageStats queryStatsForPackage(Context context, String packageName) {
        if (mStorageStatsManager == null) {
            mStorageStatsManager = (StorageStatsManager) context.getSystemService(Context.STORAGE_STATS_SERVICE);
            mUserHandle = UserHandle.getUserHandleForUid(-2);
        }
        StorageStats stats = null;
        try {
            stats = mStorageStatsManager.queryStatsForPackage(StorageManager.UUID_DEFAULT, packageName, mUserHandle);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return stats;
    }

    ApkListActivity.Model currentModel;

    public void setModel(ApkListActivity.Model model) {
        currentModel = model;
        notifyDataSetChanged();
    }

    private class AppInfo {
        String PackageName;
        String size;
    }

    @Override
    public int getItemCount() {
        return ArrayUtils.size(mItems);
    }

    private static final String TAG = "ApkListAdapter";

    /**
     * apk安装包的目录
     *
     * @param packageInfo
     * @return
     */

    private String getAppSourceDir(PackageInfo packageInfo) {
        return packageInfo.applicationInfo.sourceDir;
    }

    private String getAppDataDir(PackageInfo packageInfo) {
        return packageInfo.applicationInfo.dataDir;
    }

    protected class ViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.tvName)
        TextView tvName;
        @BindView(R.id.tvSize)
        TextView tvSize;
        @BindView(R.id.ivIcon)
        ImageView ivIcon;
        @BindView(R.id.cbChecked)
        CheckBox cbChecked;

        public ViewHolder(View itemView) {
            super(itemView);
//            R.layout.adapter_item_apk_list
            bindButterKnife(itemView);
        }

        private void bindButterKnife(View itemView) {
            ButterKnife.bind(this, itemView);
        }
    }
}
